/**
 * @file uart.c
 * @brief 串口处理
 *
 * @author 钟涛
 *
 * @date 2022-05-09
 *
 * @copyright 海南大学 - 追光者
 */

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#include "app_main.h"
#include <string.h>

#define DBG_TAG "uart"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

uint8_t disease[18];

rt_device_t dev_uart3;
static struct rt_semaphore rx_sem; /* 用于接收消息的信号量 */

/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    /* 串口接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&rx_sem);

    return RT_EOK;
}

uint8_t iap_packet[20];
int iap_readIndex;
const uint8_t HEADERS[] = { '?', '!' };
/**
 * @brief 读取数据包
 *
 * @param ch 每次收到的一个字节
 */
void iap_readPacket(uint8_t ch)
{
    iap_packet[iap_readIndex++] = ch;
    if (iap_readIndex <= sizeof(HEADERS))
    {
        /* 不符合帧头则归零 */
        if (ch != HEADERS[iap_readIndex - 1])
        {
            iap_readIndex = 0;
        }
    }
    else if (iap_readIndex == 20)
    {
        /* 读到一整个数据包，校验帧尾和校验和等 */
        iap_readIndex = 0;
        LOG_D("recv full packet: %s", iap_packet);
        memcpy(disease, iap_packet + 2, 18);
        rt_event_send(s_event, EVENT_UPLOAD_LIGHT);
        rt_event_send(s_event, EVENT_REQ_BEEP);
    }
}

void uart3_recv_thread(void *params)
{
    char ch;
    while (1)
    {
        /* 从串口读取一个字节的数据，没有读取到则等待接收信号量 */
        while (rt_device_read(dev_uart3, 0, &ch, 1) != 1)
        {
            /* 阻塞等待接收信号量，等到信号量后再次读取数据 */
            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
        }
        // 处理ch...
        LOG_D("recv ch: %02x", ch);
        iap_readPacket(ch);
    }
}

void beep_thread(void *params)
{
    while (1)
    {
        rt_event_recv(s_event, EVENT_REQ_BEEP, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, NULL);
        rt_pin_write(BEEP_PIN, PIN_HIGH);
        rt_pin_write(SPRAY_PIN, PIN_HIGH);
        rt_thread_mdelay(1000);
        rt_pin_write(BEEP_PIN, PIN_LOW);
        rt_pin_write(SPRAY_PIN, PIN_LOW);
    }
}

static int uart_init(void)
{
    dev_uart3 = rt_device_find(UART3_DEV_NAME);

    rt_pin_mode(SPRAY_PIN, PIN_MODE_OUTPUT);

    /* 初始化信号量 */
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
    rt_device_open(dev_uart3, RT_DEVICE_FLAG_INT_RX);
    rt_device_set_rx_indicate(dev_uart3, uart_input);

    rt_thread_t thread = rt_thread_create("uart3", uart3_recv_thread, NULL, 2048, PRIO_UPLOAD, 10);
    rt_thread_startup(thread);

    thread = rt_thread_create("beep", beep_thread, NULL, 512, PRIO_BEEP, 10);
    rt_thread_startup(thread);

    return 0;
}
INIT_PREV_EXPORT(uart_init);
